package org.miniframework.mvc.processor.impl;

import lombok.extern.slf4j.Slf4j;
import org.miniframework.mvc.RequestProcessorChain;
import org.miniframework.mvc.processor.RequestProcessor;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;

/**
 * 请静态资源请求处理，包括但不限于图片、css、以及js文件等
 *  <p>
 *  * 在tomcat中真正管理Servlet容器的是Context容器,一个Context对应一个web工程,Context代表servlet的上下文.具备servlet运行的基本环境,管理其中的
 *  * servlet实例.,servlet实例在Context中以Wrapper形式存在的.一个Wrapper装有一个Servlet实例,他主要负责管理一个Servlet.包装其装载初始化,执行以及资源回收等,Wrapper是
 *  * 最底层的容器,所以为了将请求转发给Servlet进行处理,我们需要从从Context中获取到对应的Wrapper实例,
 *  * Context如何获取到-- DisPatchServlet中进行获取--继承了HTTPServlet,具有getServletContext的功能,
 *  * <p>
 *  * 但是在tomcat中Wrapper并不是叫做Wrapper,而是叫做RequestDispatcher,可能是因为Wrapper需要将请求派发给Servlet进行处理的原因.
 */

@Slf4j
public class StaticResourceRequestProcessor implements RequestProcessor {

    public static final String STATIC = "/static";
    public static final String DEFAULT_SERVLET = "default";
    // tomcat默认请求派发器RequestDispatcher的名称
    private RequestDispatcher defaultServlet;

    public StaticResourceRequestProcessor(ServletContext servletContext){
        this.defaultServlet = servletContext.getNamedDispatcher(DEFAULT_SERVLET);
        if (this.defaultServlet == null){
            throw new RuntimeException("There is no default tomcat servlet");
        }
        log.info("The default servlet for static resource is {}", DEFAULT_SERVLET);
    }

    /**
     * 规定静态资源放在 static目录下 于是进行解析路径为static开头,则为静态资源访问
     * @param chain 调用链,用于结果处理参数的组装,以及处理时必要的参数信息传递
     * @return
     * @throws Exception
     */
    @Override
    public boolean process(RequestProcessorChain chain) throws Exception {
        String path = chain.getRequestPath();
        if (isStatic(path)){
            // 使用tomcat默认servlet进行转发到静态资源上,进行放行处理.
            defaultServlet.forward(chain.getRequest(),chain.getResponse());
            return false;
        }
        return true;
    }

    /**
     * 判断资源是否为static资源
     * @param path 访问路径
     * @return boolean
     */
    private boolean isStatic(String path){
        return path.startsWith(STATIC);
    }
}
